import jwt
from django.conf import settings
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

from utils import return_code


class CurrentUser(object):
    def __init__(self, user_id, username, exp):
        self.user_id = user_id
        self.username = username
        self.exp = exp


class MtbAuthenticationFailed(AuthenticationFailed):
    status_code = 200


class JwtTokenAuthentication(BaseAuthentication):

    def authenticate(self, request):
        # OPTIONS
        # 读取用户提交的jwt token
        # url中获取 token = request.query_params.get("token")
        # token = request.query_params.get("token")

        # 去请求头获取 Authorization: eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImNoaWRhZnkiLCJleHAiOjE2NTQxNjU4NzJ9.kkNiBA-XlvUvxYCE6PBOonbcQMtFHabu0XSq4rk5ViQ
        token = request.META.get('HTTP_AUTHORIZATION')  # token封装在请求头里，就不会在url里能看到了
        if not token:
            # AuthenticationFailed封装了 状态码=>401。内容=>{code:2000,error:"认证失败"}
            raise AuthenticationFailed({"code": return_code.AUTH_FAILED, "error": "认证失败"})

        try:
            # 从token中获取payload【校验合法性，并获取payload】
            payload = jwt.decode(token, settings.SECRET_KEY, ["HS256"])
            # print(payload)  # {'user_id': 1, 'username': 'chidafy', 'exp': 1654165872}

            # return payload, token
            # 把payload的字典数据封装到类里
            return CurrentUser(**payload), token  # 源码内将这两个值赋值给了： request.user, request.auth

        except Exception as e:
            # 状态码=>200 ，内容=>{code:2000,error:"认证失败"}
            raise MtbAuthenticationFailed({"code": return_code.AUTH_FAILED, "error": "认证失败"})

    def authenticate_header(self, request):
        return 'Bearer realm="API"'
